package view_server

import (
	"bigdevops/src/cache"
	"bigdevops/src/common"
	"bigdevops/src/config"
	"bigdevops/src/models"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"github.com/prometheus/common/model"
	"github.com/prometheus/prometheus/discovery/targetgroup"
	"go.uber.org/zap"
	"strconv"
	"strings"
)

type tmpNode struct {
	Title    string     `json:"title"`
	Key      string     `json:"key"`
	Children []*tmpNode `json:"children,omitempty"`
	Pid      int        `json:"pid"`
	Level    int        `json:"level"`
}

func getStreeNodeListMock(c *gin.Context) {
	// 拿到这个人用户 对应的role列表
	// 	遍历 role列表 找到 Menu list
	// 在拼装父子结构 返回的是数组 第一层 father 第2层children

	// 	遍历 role列表 找到 Menu list
	// 在拼装父子结构 返回的是数组 第一层 father 第2层children

	//sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)

	f1 := &tmpNode{
		Title:    "infra",
		Key:      "infra",
		Children: []*tmpNode{},
		Level:    1,
	}
	f2 := &tmpNode{
		Title:    "data",
		Key:      "data",
		Children: []*tmpNode{},
		Level:    1,
	}
	nodes := []*tmpNode{}
	uuid := 1
	for i := 1; i < 4; i++ {

		n1 := &tmpNode{
			Title:    fmt.Sprintf("infra-%d", i+1),
			Key:      fmt.Sprintf("infra-%d", i+1),
			Children: []*tmpNode{},
			Pid:      uuid,
			Level:    2,
		}

		n2 := &tmpNode{
			Title:    fmt.Sprintf("data-%d", i+1),
			Key:      fmt.Sprintf("data-%d", i+1),
			Children: []*tmpNode{},
			Pid:      uuid,
			Level:    2,
		}

		for j := 1; j < 4; j++ {
			n11 := &tmpNode{
				Title:    fmt.Sprintf("infra-n11-%d", j+1),
				Key:      fmt.Sprintf("infra-n11-%d", j+1),
				Children: []*tmpNode{},
				Pid:      uuid,
				Level:    3,
			}

			n21 := &tmpNode{
				Title:    fmt.Sprintf("data-n21-%d", j+1),
				Key:      fmt.Sprintf("data-n21-%d", j+1),
				Children: []*tmpNode{},
				Pid:      uuid,
				Level:    3,
			}
			n1.Children = append(n1.Children, n11)
			n2.Children = append(n2.Children, n21)
			uuid++
		}
		f1.Children = append(f1.Children, n1)
		f2.Children = append(f2.Children, n2)
		uuid++
	}
	nodes = append(nodes, f1)
	nodes = append(nodes, f2)

	common.OkWithDetailed(nodes, "ok", c)
}

func getStreeNodeList(c *gin.Context) {
	// 拿到这个人用户 对应的role列表
	// 	遍历 role列表 找到 Menu list
	// 在拼装父子结构 返回的是数组 第一层 father 第2层children

	// 	遍历 role列表 找到 Menu list
	// 在拼装父子结构 返回的是数组 第一层 father 第2层children

	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	streeNodes, err := models.GetStreeNodeAll()
	if err != nil {
		sc.Logger.Error("去数据库中拿所有的服务树节点错误",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("去数据库中拿所有的服务树节点错误:%v", err.Error()), c)
		return
	}
	// TODO 拼接 children
	// 准备全员id map
	allMap := map[uint]*models.StreeNode{}
	topMap := map[uint]*models.StreeNode{}

	pidMap := map[uint][]*models.StreeNode{}
	// 准备
	// 遍历第一轮
	for _, streeNode := range streeNodes {
		streeNode := streeNode
		//streeNode.Key = streeNode.ID
		streeNode.Key = fmt.Sprintf("%d", streeNode.ID)

		allMap[streeNode.ID] = streeNode
		if streeNode.Pid == 0 {
			topMap[streeNode.ID] = streeNode
			continue
		}

		// 同一层级的放到一起
		childs, ok := pidMap[streeNode.Pid]
		if !ok {
			childs = []*models.StreeNode{}
		}
		childs = append(childs, streeNode)
		pidMap[streeNode.Pid] = childs

	}
	// 再遍历allMap 回填他们的 children 列表

	for id, node := range allMap {
		id := id
		node := node

		childs, ok := pidMap[id]
		if ok {
			node.Children = childs
		}

	}

	finalNodes := []*models.StreeNode{}
	// 遍历第一层级 的map
	for _, topNode := range topMap {
		//topPid:=topPid
		topNode := topNode
		finalNodes = append(finalNodes, topNode)

	}

	// 遍历顶级的 节点

	common.OkWithDetailed(finalNodes, "ok", c)

}

// 这里也应该做权限校验：不能让这个人拉到所有的树节点
func getStreeNodeSelect(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	// 获取父级，上层的
	levelLt, _ := strconv.Atoi(c.DefaultQuery("levelLt", ""))
	levelNum, _ := strconv.Atoi(c.DefaultQuery("levelNum", ""))

	streeNodes, err := models.GetStreeNodeAll()
	if err != nil {
		sc.Logger.Error("去数据库中拿所有的服务树节点错误",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("去数据库中拿所有的服务树节点错误:%v", err.Error()), c)
		return
	}

	finalRes := []*models.StreeNode{}

	for _, streeNode := range streeNodes {
		streeNode := streeNode
		if levelNum > 0 && streeNode.Level != levelNum {
			continue
		}

		if levelLt > 0 && streeNode.Level > levelLt {
			continue
		}

		streeNode.FillFrontAllDataSimple()
		finalRes = append(finalRes, streeNode)
	}
	common.OkWithDetailed(finalRes, "ok", c)
}

func getStreeNodeSelectWithCicdItem(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	// 获取父级，上层的

	// 先去找到服务发布项里面的所有treeNodeids
	dbAllCicdItems, err := models.GetCicdDeployItemAll()
	if err != nil {
		msg := fmt.Sprintf("去数据库中拿所有的服务发布项错误：%v", err)
		sc.Logger.Error(msg,
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(msg, c)
		return
	}

	ids := []int{}
	for _, cicdItem := range dbAllCicdItems {
		cicdItem := cicdItem
		ids = append(ids, int(cicdItem.TreeNodeId))
	}

	streeNodes, err := models.GetStreeNodeByIds(ids)
	if err != nil {
		msg := fmt.Sprintf("去数据库中根据服务发布项id拿服务树错误：%v", err)
		sc.Logger.Error(msg,
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(msg, c)
		return
	}
	finalRes := []*models.StreeNode{}

	for _, streeNode := range streeNodes {
		streeNode := streeNode

		streeNode.FillFrontAllDataSimple()
		finalRes = append(finalRes, streeNode)
	}
	common.OkWithDetailed(finalRes, "ok", c)
}

// 新增 删除 修改树节点 的通用 权限校验方法
// =true 代表有权限，=false代表没权限
func streeNodeOpsAdminPermissionCheck(node *models.StreeNode, c *gin.Context) (bool, error) {

	userName := c.MustGet(common.GIN_CTX_JWT_USER_NAME).(string)
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	reqUser, err := models.GetUserByUserName(userName)
	if err != nil {
		sc.Logger.Error("通过token解析到的userName去数据库中找User失败",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("通过token解析到的userName去数据库中找User失败:%v", err.Error()), c)
		return false, err
	}

	// 这里支持服务账号
	if reqUser.AccountType == 2 {
		return true, nil
	}

	sc.Logger.Debug("服务树节点权限校验开始",
		zap.String("用户", userName),
		//zap.Any("用户详情", reqUser),
		zap.Any("node", node),
	)

	// 如果是超管就 放行
	isSuper := false
	for _, role := range reqUser.Roles {
		role := role
		if role.RoleValue == sc.SuperRoleName {
			isSuper = true
			break
		}
	}

	if isSuper {
		return true, nil
	}

	pass := false

	// 否则的话 ，校验你在不在	运维管理员列表里面 或者父级
	for node != nil {

		// 先遍历本级 opsaadmin
		for _, user := range node.OpsAdmins {

			user := user
			//sc.Logger.Info("先遍历本级 opsaadmin",
			//	zap.String("user", reqUser.Username),
			//	zap.String("节点", node.Title),
			//	zap.String("节点的opsaadmin", user.Username),
			//)
			if user.Username == reqUser.Username {
				pass = true
				break
			}

		}
		if pass {
			break
		}

		// 到这里说明 本级 opsaadmin已经遍历完了
		// 就得找父亲
		father, _ := models.GetStreeNodeById(int(node.Pid))
		if father == nil {
			break
		}
		//sc.Logger.Info("遍历完本级opsaadmin后寻找father",
		//	zap.String("user", reqUser.Username),
		//	zap.String("节点", node.Title),
		//	zap.String("father", father.Title),
		//)
		node = father

	}

	sc.Logger.Info("服务树节点权限校验结果",
		zap.Bool("是否通过", pass),
		zap.String("用户", userName),
		//zap.Any("node", node),
	)

	return pass, nil

}

func createStreeNode(c *gin.Context) {

	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	// 校验一下 menu字段
	var reqNode models.StreeNode
	err := c.ShouldBindJSON(&reqNode)
	if err != nil {
		sc.Logger.Error("解析新增reqNode请求失败", zap.Any("reqNode", reqNode), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 在这里校验字段，是否必填，范围是否正确
	err = validate.Struct(reqNode)
	if err != nil {

		// 这里为什么要判断错误是否是 ValidationErrors
		if errors, ok := err.(validator.ValidationErrors); ok {
			common.ReqBadFailWithWithDetailed(

				gin.H{
					"翻译前": err.Error(),
					"翻译后": errors.Translate(trans),
				},
				"请求出错",
				c,
			)
			return
		}
		common.ReqBadFailWithMessage(err.Error(), c)
		return

	}

	// 在创建节点前要校验权限
	pass, err := streeNodeOpsAdminPermissionCheck(&reqNode, c)
	if err != nil {
		sc.Logger.Error("服务树节点权限校验失败", zap.Any("reqNode", reqNode), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	if !pass {
		sc.Logger.Error("服务树节点权限校验未通过", zap.Any("reqNode", reqNode), zap.Error(err))
		common.Req403WithWithMessage("服务树节点权限校验未通过", c)
		return

	}

	err = reqNode.CreateOne()
	if err != nil {
		sc.Logger.Error("创建Api错误", zap.Any("reqNode", reqNode), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	common.OkWithMessage("创建成功", c)
}

func deleteStreeNode(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	// 校验一下 menu字段
	id := c.Param("id")
	sc.Logger.Info("删除树节点", zap.Any("id", id))

	// 先 去db中根据id找到这个对象
	intVar, _ := strconv.Atoi(id)
	dbNode, err := models.GetStreeNodeById(intVar)
	if err != nil {
		sc.Logger.Error("根据id找树节点错误", zap.Any("树节点", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 在创建节点前要校验权限
	pass, err := streeNodeOpsAdminPermissionCheck(dbNode, c)
	if err != nil {
		sc.Logger.Error("服务树节点权限校验失败", zap.Any("reqNode", dbNode), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	if !pass {
		sc.Logger.Error("服务树节点权限校验未通过", zap.Any("reqNode", dbNode), zap.Error(err))
		common.Req403WithWithMessage("服务树节点权限校验未通过", c)
		return

	}

	// 根据dbNode的 Id去查 pid是这个

	childrens, _ := models.GetStreeNodesByPid(int(dbNode.ID))

	// 如果dbNode的children不为空 那么不允许删除
	if childrens != nil && len(childrens) > 0 {
		err = errors.New(fmt.Sprintf("不允许删除非叶子节点 id:%v title:%v",
			id,
			dbNode.Title,
		))
		sc.Logger.Error("不允许删除非叶子节点",
			zap.Error(err),
		)
		common.FailWithMessage(err.Error(), c)
		return
	}

	err = dbNode.DeleteOne()
	if err != nil {
		sc.Logger.Error("根据id删除树节点错误", zap.Any("树节点", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}
	common.OkWithMessage("删除成功", c)
}

// 作用：获取所有顶级节点，为了下一轮进行子节点的展开
func getTopStreeNodes(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	sc.Logger.Info("获取顶级节点前")
	topNodes, err := models.GetStreeNodeByLevel(1)
	sc.Logger.Info("获取顶级节点后")
	if err != nil {
		sc.Logger.Error("去数据库中拿所有的顶级服务树节点错误",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("去数据库中拿所有的顶级服务树节点错误:%v", err.Error()), c)
		return
	}

	for _, node := range topNodes {
		node := node
		node.FillFrontAllDataNew()
		pass, _ := streeNodeOpsAdminPermissionCheck(node, c)
		node.CanAdminNode = pass
	}

	common.OkWithDetailed(topNodes, "ok", c)
}

// 作用：获取所有顶级节点，为了下一轮进行子节点的展开
func getTopStreeNodesUseCache(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	sc.Logger.Info("获取顶级节点前")
	topNodes, err := models.GetStreeNodeByLevel(1)
	sc.Logger.Info("获取顶级节点后")
	if err != nil {
		sc.Logger.Error("去数据库中拿所有的顶级服务树节点错误",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("去数据库中拿所有的顶级服务树节点错误:%v", err.Error()), c)
		return
	}

	streeC := c.MustGet(common.GIN_CTX_STREE_CACHE).(*cache.StreeCache)
	for _, node := range topNodes {
		node := node

		node.FillFrontAllDataWithCache(streeC.StreeNodeCacahe)
		pass, _ := streeNodeOpsAdminPermissionCheck(node, c)
		node.CanAdminNode = pass
	}

	common.OkWithDetailed(topNodes, "ok", c)
}

// 获取所有的叶子节点 过滤其中 没有绑定机器的

func getLeafStreeNodes(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	topNodes, err := models.GetStreeNodeAllLeaf()
	if err != nil {
		sc.Logger.Error("去数据库中拿所有的叶子服务树节点错误",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("去数据库中拿所有的叶子服务树节点错误:%v", err.Error()), c)
		return
	}
	leafNodes := []*models.StreeNode{}

	for _, node := range topNodes {

		node := node
		node.FillFrontAllData()
		if node.BindEcss == nil || len(node.BindEcss) == 0 {
			continue
		}
		leafNodes = append(leafNodes, node)

	}

	//common.OkWithDetailed(leafNodes, "ok", c)

	resp := &ResponseResourceCommon{
		//Total: models.GetMonitorScrapeJobCount(), 因为是带了查询条件的 所以 count 不能是all 而是 过滤后的total

		Total: len(leafNodes),
		Items: leafNodes,
	}

	common.OkWithDetailed(resp, "ok", c)
}

// 传参叶子节点 id数组 ids ，port 端口传入 ，返回 所有相关叶子节点 ip+port 的数组
// [
//    {
//        "targets": ["10.0.10.2:9100", "10.0.10.3:9100", "10.0.10.4:9100", "10.0.10.5:9100"],
//        "labels": {
//            "__meta_datacenter": "london",
//            "__meta_prometheus_job": "node"
//        }
//    },
//    {
//        "targets": ["10.0.40.2:9100", "10.0.40.3:9100"],
//        "labels": {
//            "__meta_datacenter": "london",
//            "__meta_prometheus_job": "alertmanager"
//        }
//    },
//    {
//        "targets": ["10.0.40.2:9093", "10.0.40.3:9093"],
//        "labels": {
//            "__meta_datacenter": "newyork",
//            "__meta_prometheus_job": "alertmanager"
//        }
//    }
//]

// 参考  D:\nyy_work\go_path\src\github.com\prometheus\prometheus\discovery\http\http_test.go
/*

	expectedTargets := []*targetgroup.Group{
		{
			Targets: []model.LabelSet{
				{
					model.AddressLabel: model.LabelValue("127.0.0.1:9090"),
				},
			},
			Labels: model.LabelSet{
				model.LabelName("__meta_datacenter"): model.LabelValue("bru1"),
				model.LabelName("__meta_url"):        model.LabelValue(ts.URL + "/http_sd.good.json"),
			},
			Source: urlSource(ts.URL+"/http_sd.good.json", 0),
		},
	}
*/

// eg  http://localhost/noAuth/getLeafStreeNodeBindIps?port=999&leafNodeIds=1,2,13

func getLeafStreeNodeBindIps(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)

	// 逗号分割
	leafNodeIds := c.DefaultQuery("leafNodeIds", "")

	port, _ := strconv.Atoi(c.DefaultQuery("port", ""))
	if port == 0 {
		err := fmt.Errorf("prome监控http服务树服务发现未传参port")
		sc.Logger.Error(err.Error())

		common.FailWithMessage(err.Error(), c)
		return
	}

	if leafNodeIds == "" {
		err := fmt.Errorf("prome监控http服务树服务发现未传参leafNodeIds")
		sc.Logger.Error(err.Error())

		common.FailWithMessage(err.Error(), c)
		return
	}

	leafNodeIdsArr := strings.Split(leafNodeIds, ",")
	if len(leafNodeIdsArr) == 0 {
		return
	}

	leafNodeIdsInt := []int{}
	for _, ids := range leafNodeIdsArr {
		idInt, err := strconv.Atoi(ids)
		if err != nil {
			continue
		}
		leafNodeIdsInt = append(leafNodeIdsInt, idInt)

	}
	if len(leafNodeIdsInt) == 0 {
		return
	}
	leadfNodes, err := models.GetStreeNodeByIds(leafNodeIdsInt)
	if err != nil {
		msg := "prome监控http服务树服务发现 根据ids获取叶子节点错误"
		sc.Logger.Error(msg,
			zap.Error(err),
			zap.Any("叶子节点", leafNodeIds),
		)
	}

	sdTargetsMap := map[string]*targetgroup.Group{}
	// 遍历叶子节点 找到绑定的机器

	for _, leadfNode := range leadfNodes {
		leadfNode := leadfNode
		if leadfNode.BindEcss == nil {
			continue
		}
		if len(leadfNode.BindEcss) == 0 {
			continue
		}

		for _, ecs := range leadfNode.BindEcss {
			ecs := ecs
			oneTarget := &targetgroup.Group{
				Targets: []model.LabelSet{
					{
						model.AddressLabel: model.LabelValue(fmt.Sprintf("%v:%v", ecs.IpAddr, port)),
					},
				},
				Labels: model.LabelSet{
					//model.LabelName("__meta_url"):        model.LabelValue(ts.URL + "/http_sd.good.json"),
				},
			}
			// 设置虚拟机的标签
			for _, tag := range ecs.Tags {
				tags := strings.Split(tag, "=")
				if len(tags) != 2 {
					continue
				}
				tagK := tags[0]
				tagV := tags[1]
				oneTarget.Labels[model.LabelName(tagK)] = model.LabelValue(tagV)
			}

			sdTargetsMap[ecs.IpAddr] = oneTarget

		}

	}
	fRes := []*targetgroup.Group{}
	for _, v := range sdTargetsMap {
		v := v
		fRes = append(fRes, v)
	}
	c.JSON(200, fRes)
}

func getChildrenStreeNodes(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	// 校验一下 menu字段
	pid := c.Param("pid")
	sc.Logger.Info("获取下一层级的节点", zap.Any("pid", pid))
	streeC := c.MustGet(common.GIN_CTX_STREE_CACHE).(*cache.StreeCache)
	// 先 去db中根据id找到这个对象
	intVar, _ := strconv.Atoi(pid)
	childrens, err := models.GetStreeNodesByPid(intVar)
	if err != nil {
		sc.Logger.Error("根据pid找子节点错误", zap.Any("树节点", pid), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}
	for _, node := range childrens {
		node := node
		//node.FillFrontAllData()
		node.FillFrontAllDataWithCache(streeC.StreeNodeCacahe)
		pass, _ := streeNodeOpsAdminPermissionCheck(node, c)
		node.CanAdminNode = pass

		//for _, user := range node.OpsAdmins {
		//	user := user
		//	node.OpsAdminUsers = append(node.OpsAdminUsers, user.Username)
		//}
	}

	common.OkWithDetailed(childrens, "ok", c)

}

func updateStreeNode(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	// 校验一下 menu字段
	var reqNode models.StreeNode
	err := c.ShouldBindJSON(&reqNode)
	if err != nil {
		sc.Logger.Error("解析更新服务树节点请求失败", zap.Any("树节点", reqNode), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 在这里校验字段，是否必填，范围是否正确
	err = validate.Struct(reqNode)
	if err != nil {

		// 这里为什么要判断错误是否是 ValidationErrors
		if errors, ok := err.(validator.ValidationErrors); ok {
			common.ReqBadFailWithWithDetailed(

				gin.H{
					"翻译前": err.Error(),
					"翻译后": errors.Translate(trans),
				},
				"请求出错",
				c,
			)
			return
		}
		common.ReqBadFailWithMessage(err.Error(), c)
		return

	}

	_, err = models.GetStreeNodeById(int(reqNode.ID))
	if err != nil {
		sc.Logger.Error("根据id找树节点错误", zap.Any("树节点", reqNode), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 在创建节点前要校验权限
	pass, err := streeNodeOpsAdminPermissionCheck(&reqNode, c)
	if err != nil {
		sc.Logger.Error("服务树节点权限校验失败", zap.Any("reqNode", &reqNode), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	if !pass {
		sc.Logger.Error("服务树节点权限校验未通过", zap.Any("reqNode", &reqNode), zap.Error(err))
		common.Req403WithWithMessage("服务树节点权限校验未通过", c)
		return

	}

	usersOpsAdmin := make([]*models.User, 0)
	usersRdAdmin := make([]*models.User, 0)
	usersRdMember := make([]*models.User, 0)
	// 遍历角色menu 列表 找到角色
	for _, userName := range reqNode.OpsAdminUsers {
		dbUser, err := models.GetUserByUserName(userName)
		if err != nil {
			sc.Logger.Error("树节点根据userName找用户错误", zap.Any("树节点", reqNode), zap.Error(err))
			common.FailWithMessage(err.Error(), c)
			return
		}
		usersOpsAdmin = append(usersOpsAdmin, dbUser)

	}
	for _, userName := range reqNode.RdAdminUsers {
		dbUser, err := models.GetUserByUserName(userName)
		if err != nil {
			sc.Logger.Error("树节点根据userName找用户错误", zap.Any("树节点", reqNode), zap.Error(err))
			common.FailWithMessage(err.Error(), c)
			return
		}
		usersRdAdmin = append(usersRdAdmin, dbUser)

	}
	for _, userName := range reqNode.RdMemberUsers {
		dbUser, err := models.GetUserByUserName(userName)
		if err != nil {
			sc.Logger.Error("树节点根据userName找用户错误", zap.Any("树节点", reqNode), zap.Error(err))
			common.FailWithMessage(err.Error(), c)
			return
		}
		usersRdMember = append(usersRdMember, dbUser)

	}

	// 将运维负责人设置，即使是空的也要设置：
	// 原来非空，现在为空 代表删除人员了
	reqNode.OpsAdmins = usersOpsAdmin
	reqNode.RdAdmins = usersRdAdmin
	reqNode.RdMembers = usersRdMember
	err = reqNode.UpdateStreeNode()
	if err != nil {
		sc.Logger.Error("更新树节点和关联的运维负责人错误", zap.Any("树节点", reqNode), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	common.OkWithMessage("更新成功", c)
	sc.Logger.Info("更新树节点和关联的运维负责人成功", zap.Any("树节点", reqNode))
}
